/**
 * Places view uses a switcher widget to show lists of categories and a list of places.
 * The main categories are shown first. After choosing a category user can navigate 
 * deeper into subcategories or show places in the selected category or subcategory. 
 */

(function() {
	var view = View("places-view");
	
	qype.views.placesView = view;

	var content;
	var contentStack = [];

	var links;
	
	var location = "";
	var locationTitle = "&nbsp;";
	
	view.getHtml = function() {
		return sprintf('<div id="%s"></div>', view.getId());
	};

	view.init = function() {
		this.initBack();
		content = SwitcherWidget();
		this.getContainer().append(content.getHtml());
		resetCategoryViews(1);
		content.showView(0);
	};
	
	view.setLocation = function(loc, title) {
		location = loc;
		locationTitle = title;
		contentStack[0].header.html(title);
	};

	function backId(index) {
		return view.getId() + "-back-" + index;
	}

	function resetCategoryViews(index) {
		content.removeViews(index);
		var size = content.size();
		for(var i = 0; i <= index; i++) {
			if (!contentStack[i]) {
				contentStack[i] = CategoryView(i);
			}
			if(i >= size) {
				content.addView(contentStack[i].getHtml());
				contentStack[i].toggleLoading(true);
				if(index > 0) {
					contentStack[i].setBackLink(content.linkMwl(i - 1) + contentStack[i].loadingMwl());
				}
			}
		}
	}

	view.setLinks = function(l) {
		links = l;
		contentStack[0].setBackLink(l.backToLocation);
	};
	
	function CategoryView(index) {
		var id = 'places-stack-item-'+index;
		var that = Widget({id: id});

		that.loadingHeader = ElementWidget({id: id+"-loading-header", tag: "h1", html: "&nbsp;"});
		that.loading = LoadingWidget({id: id+"-loading", label: qype.strings.loading});
		that.header = ElementWidget({id: id+"-header", tag: "h1", html: "&nbsp;"});
		that.list = ListWidget({id: id+"-list", emptyContent: sprintf('<div class="no-results">%s</div>', qype.strings.noResults)});
		
		that.getHtml = function() {
			var html = [
				this.loadingHeader.getHtml(),
				this.loading.getHtml(),
				this.header.getHtml(),
				this.list.getHtml()
			];
			return html.join("");
		};
		
		that.setBackLink = function(onclickMwl) {
			view.addBack(backId(index), onclickMwl + (index > 0 ? view.showBackMwl(backId(index - 1)) : ""));
		};
		
		that.toggleLoading = function(display) {
			this.loadingHeader.toggle(display);
			this.loading.toggle(display);
			this.header.toggle(!display);
			this.list.toggle(!display);
		};
		
		that.loadingMwl = function() {
			return this.loading.showLoadingMwl() + this.loadingHeader.showMwl() + this.loading.showMwl() + this.header.hideMwl() + this.list.hideMwl();
		};
		
		that.showError = function(category, title, viewIndex, isPlaces, status) {
			this.list.populate([]);
			this.loading.setError(util.networkErrorMessage(status, this.loading.showLoadingMwl() + (isPlaces ? loadPlacesMwl(category, title, viewIndex) : loadCategoriesMwl(category, title, viewIndex))));
			this.loading.showError();
			this.toggleLoading(true);
		};
		
		return that;
	}

	function categoriesToListItems(entries, onclickTemplate, category, title, viewIndex) {
		function getLink(entry, relRegExp) {
			return (util.getLink(entry, relRegExp) || {href: ''}).href;
		}
		
		function getId(entry) {
			return getLink(entry, /^self$/).split('/').pop();
		}
		
		function hasChildren(entry) {
			return !!getLink(entry, /children$/);
		}
		
		function getScript(entry) {
			// Uncomment to enable subcategories
			//if(hasChildren(entry)) {
			//	return loadCategoriesMwl(getId(entry), entry.full_title.value, viewIndex);
			//}
			return loadPlacesMwl(getId(entry), entry.full_title.value, viewIndex); 
		}
		
		function getLabel(entry) {
			var template = '<table summary="Category" cellspacing="0" cellpadding="0" border="0"><tr>'+
				'<td class="category-%s"><div class="category-icon">&nbsp;</div></td>'+
				'<td><div class="category-text">%s</div></td>'+
				'</tr></table>';
			
			return sprintf(template, getId(entry), entry.full_title.value);
		}
		
		var results = $.map(entries, function(item, index) {
			return {
				onclick: sprintf(onclickTemplate, getScript(item.category)),
				name: getLabel(item.category),
				clazz: 'category-list-item'
			};
		});
		results.sort(function(a, b) {
			return (a.name > b.name) - (a.name < b.name);
		});
		if(viewIndex > 1) {
			results.unshift({
				onclick: sprintf(onclickTemplate, loadPlacesMwl(category, title, viewIndex)),
				name: qype.strings.showAll
			});
		}
		return results;
	}

	function loadCategoriesMwl(category, title, viewIndex) {
		return sprintf("qype.views.placesView.loadCategories.call(qype.views.placesView,'%s','%s',%s);", category || '', title || '', viewIndex || 0);
	}

	view.loadCategories = function(category, title, viewIndex) {
		viewIndex = viewIndex || 0;
		qype.API.get('place_categories', {
	        onSuccess: function(response) {
				resetCategoryViews(viewIndex + 1);
				contentStack[viewIndex].header.html(viewIndex ? locationTitle + ' > ' + title : locationTitle);
				var onclickTemplate = [
					view.showBackMwl(backId(viewIndex + 1)),
					content.linkMwl(viewIndex + 1),
					"%s"
				];
				var results = categoriesToListItems(response.results, onclickTemplate.join(""), category, title, viewIndex + 1);
				contentStack[viewIndex].list.populate(results);
				contentStack[viewIndex].toggleLoading(false);
	        },
	        onFailure: function(response, status) {
				contentStack[viewIndex].showError(category, title, viewIndex, false, status);
	        }
		}, category ? category + "/children" : undefined);
	};
	
	var placesCache;
	
	function placesToListItems(entries, onclickTemplate) {
		function getLabel(placedata) {
			var place = qype.models.PlaceModel(placedata);
			var template = '<div class="place-list-item-text">%s</div>' +
				'<table summary="PlaceRating" cellspacing="0" cellpadding="0" border="0"><tr>'+
				'<td class="rating"><div class="image-holder"><img class="stars%s" src="img/star.png" /></div></td>'+
				'<td><div class="place-list-item-rating-text">%s</div></td>'+
				'</tr></table>';
			return sprintf(template, placedata.title, placedata.average_rating, place.getReviewsStr());
		}

		placesCache = entries;
		var results = $.map(entries, function(item, index) {
			return {
				onclick: sprintf(onclickTemplate, index),
				name: getLabel(item.place),
				clazz: 'place-list-item'
			};
		});
		return results;
	};
	
	function loadPlacesMwl(category, title, viewIndex) {
		return sprintf("qype.views.placesView.loadPlaces.call(qype.views.placesView,'%s','%s',%s);", category || '', title || '', viewIndex || 0);
	}

	view.loadPlaces = function(category, title, viewIndex) {
		var onSuccess = function(position) {
			qype.API.get(position ? 'positions' : 'locators', {
		        onSuccess: function(response) {
					contentStack[viewIndex].header.html(locationTitle + ' > ' + title);
					var onclickTemplate = [
						links.place,
						"qype.views.placesView.loadPlace.call(qype.views.placesView, '%s');"
					];
					contentStack[viewIndex].list.populate(placesToListItems(response.results, onclickTemplate.join("")));
					contentStack[viewIndex].toggleLoading(false);
		        },
		        onFailure: function(response, status) {
					contentStack[viewIndex].showError(category, title, viewIndex, true, status);
		        }
			}, (position ? [position.coords.latitude, position.coords.longitude].join(',')  : location) + "/places", {
				in_category: category,
				order: position ? "distance" : "rating",
				radius: '10'
			});
		};
		var onError = function() {
			contentStack[viewIndex].showError(category, title, viewIndex, true, 666);
		};
		
		if(location == "CURRENT_LOCATION") {
			if(currentPosition) onSuccess(currentPosition);
			else onError();
		}
		else onSuccess();
	};
	
	view.loadPlace = function(index) {
		qype.views.placeView.loadPlace(placesCache[index].place);
	};

	view.reset = function() {
		this.showBack(backId(0));
	};

	view.resetMwl = function() {
		return content.linkMwl("0", true) + contentStack[1].loadingMwl() + this.showBackMwl(backId(0)); 
	};
})();
